package service

import (
	"fmt"
	"go-admin/define"
	"go-admin/models"
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

func GetRoleList(c *gin.Context) {
	in := &GetUserListRequest{NewQueryRequest()}
	err := c.ShouldBindQuery(in)

	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "参数异常",
		})
		return
	}

	var (
		count int64
		list  = make([]*GetRoleListReply, 0)
	)
	err = models.GetRoleList(in.Keyword).Count(&count).Offset((in.Page - 1) * in.Size).Limit(in.Size).Find(&list).Error
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "数据库异常",
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "加载成功",
		"result": gin.H{
			"list":  list,
			"total": count,
		},
	})
}

func AddRole(c *gin.Context) {
	in := &AddRoleRequest{}
	err := c.ShouldBindJSON(in)
	if err != nil {
		c.JSON(http.StatusOK, define.ErrorResult("参数异常"))
		fmt.Println(err)
		return
	}

	//判断角色名称是否已经存在
	var count int64
	err = models.DB.Model(new(models.SysRole)).Where("name = ?", in.Name).Count(&count).Error
	if err != nil {
		c.JSON(http.StatusOK, define.ErrorResult("数据库异常，添加角色失败!"))
		return
	}

	//大于0，说明角色名称已经存在
	if count > 0 {
		c.JSON(http.StatusOK, define.ErrorResult("添加角色失败，该角色名称已存在！"))
		return
	}

	//给角色授权的菜单
	rms := make([]*models.RoleMenu, len(in.MenuId))
	for i := range rms {
		rms[i] = &models.RoleMenu{
			MenuId: in.MenuId[i],
		}
	}

	//组建角色数据
	rb := &models.SysRole{
		Name:    in.Name,
		Sort:    in.Sort,
		IsAdmin: in.IsAdmin,
		Remarks: in.Remarks,
	}

	//新增角色数据
	err = models.DB.Transaction(func(tx *gorm.DB) error {
		//保存角色
		err = tx.Create(rb).Error
		if err != nil {
			return err
		}

		//保存被授权菜单
		for _, v := range rms {
			v.RoleId = rb.ID
		}
		if len(rms) > 0 {
			err = tx.Create(rms).Error
			if err != nil {
				return err
			}
		}
		return nil
	})

	if err != nil {
		c.JSON(http.StatusOK, define.ErrorResult("数据库异常，添加角色失败"))
		return
	}

	c.JSON(http.StatusOK, define.SuccessResult("添加角色成功"))

}

func GetRoleDetail(c *gin.Context) {
	id := c.Param("id")
	if id == "" {
		c.JSON(http.StatusOK, define.ErrorResult("ID不能为空！"))
		return
	}

	uId, err := strconv.Atoi(id)
	if err != nil {
		c.JSON(http.StatusOK, "转换异常！")
		return
	}
	data := new(GetRoleDetailReply)
	sysRole, err := models.GetRoleDetail(uint(uId))
	if err != nil {
		c.JSON(http.StatusOK, "数据库异常！")
		return
	}
	data.ID = sysRole.ID
	data.Name = sysRole.Name
	data.Sort = sysRole.Sort
	data.IsAdmin = sysRole.IsAdmin
	data.Remarks = sysRole.Remarks

	// 获取授权菜单
	menuIds, err := models.GetRoleMenuId(sysRole.ID, sysRole.IsAdmin == 1)

	if err != nil {
		c.JSON(http.StatusOK, define.ErrorResult("获取数据失败"))
		return
	}

	data.MenuId = menuIds

	c.JSON(http.StatusOK, define.SuccessResultWithData("获取数据成功", data))
}

// 更新角色信息
func UpdateRole(c *gin.Context) {
	in := &UpdateRoleRequest{}
	err := c.ShouldBindJSON(in)

	if err != nil {
		c.JSON(http.StatusOK, define.ErrorResult("参数异常"))
		return
	}
	//判断角色名称是否已经存在
	var count int64
	err = models.DB.Model(&models.SysRole{}).Where("id != ? AND name=?", in.ID, in.Name).Count(&count).Error

	if err != nil {
		c.JSON(http.StatusOK, define.ErrorResult("数据库异常"))
		return
	}

	//判断是否已经存在
	if count > 0 {
		c.JSON(http.StatusOK, define.ErrorResult("更新失败，角色名称已经存在"))
		return
	}
	//修改数据
	err = models.DB.Transaction(func(tx *gorm.DB) error {
		//更新数据
		err = models.DB.Model(&models.SysRole{}).Where("id = ?", in.ID).Updates(map[string]any{
			"name":     in.Name,
			"is_admin": in.IsAdmin,
			"sort":     in.Sort,
			"remarks":  in.Remarks,
		}).Error
		if err != nil {
			return err
		}

		// 删除该角色已授权的菜单（删除老数据）（使用Unscoped 进行硬删除）
		err = tx.Where("role_id = ?", in.ID).Unscoped().Delete(new(models.RoleMenu)).Error
		if err != nil {
			return err
		}

		//增加新授权的菜单数据
		rms := make([]*models.RoleMenu, len(in.MenuId))
		for i := range rms {
			rms[i] = &models.RoleMenu{
				RoleId: in.ID,
				MenuId: in.MenuId[i],
			}
		}

		if len(rms) > 0 {
			err = tx.Create(rms).Error
			if err != nil {
				return err
			}
		}
		return nil
	})

	if err != nil {
		c.JSON(http.StatusOK, define.ErrorResult("数据库异常"))
		return
	}

	c.JSON(http.StatusOK, define.SuccessResult("更新成功"))
}

// DeleteRole 根据ID删除角色信息
func DeleteRole(c *gin.Context) {
	id := c.Param("id")
	if id == "" {
		c.JSON(http.StatusOK, define.ErrorResult("删除失败， ID 不能为空！"))
		return
	}

	// 删除角色
	err := models.DB.Where("id = ?", id).Delete(new(models.SysRole)).Error
	if err != nil {
		c.JSON(http.StatusOK, define.ErrorResult("删除失败，数据库异常！"))
		return
	}
	c.JSON(http.StatusOK, define.SuccessResult("删除成功！"))

}

// PatchRoleAdmin 更改管理员身份
func PatchRoleAdmin(c *gin.Context) {
	id := c.Param("id")
	isAdmin := c.Param("isAdmin")

	if id == "" || isAdmin == "" {
		c.JSON(http.StatusOK, define.ErrorResult("必填参数不能为空!"))
		return
	}
	// 更改管理员身份
	err := models.DB.Model(new(models.SysRole)).Where("id = ?", id).Update("is_admin", isAdmin).Error
	if err != nil {
		c.JSON(http.StatusOK, define.ErrorResult("更新失败，数据库异常!"))
		return
	}

	c.JSON(http.StatusOK, define.SuccessResult("修改管理员身份成功!"))
}

func AllRole(c *gin.Context) {
	list := make([]*AllRoleListReply, 0)
	err := models.DB.Model(models.SysRole{}).Find(&list).Error
	if err != nil {
		c.JSON(http.StatusOK, define.ErrorResult("角色列表获取失败！"))
		return
	}

	c.JSON(http.StatusOK, define.SuccessResultWithData("加载成功", list))
}
